package com.algorithm.liyc.echa;

import com.algorithm.liyc.entity.TreeNode;

import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

/**
 * 110.平衡二叉树
 * 给定一个二叉树，判断它是否是高度平衡的二叉树。
 *
 * 本题中，一棵高度平衡二叉树定义为：一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过1。
 * 这道题目要求从根节点到叶子的路径，所以需要前序遍历，这样才方便让父节点指向孩子节点，找到对应的路径。
 * 在这道题目中将第一次涉及到回溯，因为我们要把路径记录下来，需要回溯来回退一个路径再进入另一个路径。
 *
 * @author Liyc
 * @date 2024/1/5 17:27
 **/

public class Solution10 {
    /**
     * 递归法
     * @param root
     * @return
     */
    public List<String> binaryTreePaths1(TreeNode root) {
        List<String> result = new ArrayList<>();// 存最终的结果
        if (root == null) {
            return result;
        }
        List<Integer> path = new ArrayList<>();// 作为结果中的路径

        travelbal(root, path, result);
        return result;
    }

    public void travelbal(TreeNode root, List<Integer> path, List<String> res) {
        path.add(root.val);// 前序遍历，中
        // 遇到叶子结点
        if (root.left == null && root.right == null) {
            // 输出
            StringBuffer sb = new StringBuffer();// StringBuilder用来拼接字符串，速度更快
            for (int i = 0; i < path.size() - 1; i++) {
                sb.append(path.get(i) + "-->");
            }
            sb.append(path.get(path.size() - 1));// 记录最后一个节点
            res.add(sb.toString());// 收集一个路径
            return;
        }

        // 递归和回溯是同时进行，所以要放在同一个花括号里
        if (root.left != null) {// 左
            travelbal(root.left, path, res);
            path.remove(path.size() - 1);// 回溯
        }
        if (root.right != null) {// 右
            travelbal(root.right, path, res);
            path.remove(path.size() - 1);// 回溯
        }
    }

    /**
     * 迭代法
     * @param root
     * @return
     */
    public List<String> binaryTreePaths2(TreeNode root) {
        List<String> result = new ArrayList<>();
        if (root == null) {
            return result;
        }
        // 节点和路径同时入栈
        Stack<Object> stack = new Stack<>();
        stack.add(root);
        stack.add(root.val + "");
        while (!stack.isEmpty()) {
            // 节点和路径同时出栈
            String path = (String) stack.pop();
            TreeNode node = (TreeNode) stack.pop();
            // 若找到叶子节点
            if (node.left == null && node.right == null) {
                result.add(path);
            }
            //右子节点不为空
            if (node.right != null) {
                stack.add(node.right);
                stack.add(path + "->" + node.right.val);
            }
            //左子节点不为空
            if (node.left != null) {
                stack.add(node.left);
                stack.add(path + "->" + node.left.val);
            }
        }

        return result;
    }
}
